/*
 * board.c
 *
 * Created: 6/22/2013 9:53:02 PM
 *  Author: Tim
 */ 
#include "board.h"
#include "../features/adc/adc.h"
#include "../features/dac/dac.h"
#include "../communication/comPort.h"
#include "../extFlash/flash.h"

//enables, and utilizes the internal 32MHz osc for the system clock
void clkInit_32MHz()
{
		
	OSC.CTRL |= OSC_RC32MEN_bm | OSC_RC32KEN_bm;
	while(!(OSC.STATUS & OSC_RC32MRDY_bm) || !(OSC.STATUS & OSC_RC32KRDY_bm));

	CCP = CCP_IOREG_gc;
	CLK.CTRL = CLK_SCLKSEL_RC32M_gc;

#if defined (__AVR_ATxmega32A4U__)
	OSC.RC32KCAL = ReadCalibrationByte( offsetof(NVM_PROD_SIGNATURES_t, RCOSC32K) );

	DFLLRC32M.CALB = ReadCalibrationByte( offsetof(NVM_PROD_SIGNATURES_t, RCOSC32M) );
	DFLLRC32M.CALA = ReadCalibrationByte( offsetof(NVM_PROD_SIGNATURES_t, RCOSC32MA) );
	
	OSC.DFLLCTRL = OSC_RC32MCREF_RC32K_gc;

	DFLLRC32M.CTRL |= DFLL_ENABLE_bm;
	DFLLRC32M.COMP0 = 0x12;
	DFLLRC32M.COMP1 = 0x7A;
#endif

}
void prDisable(peripheral_t pr)
{
	switch (pr)
	{
		case USB_PR:
		setMsk(PR.PRGEN,PR_USB_bm);
		break;
		case AES_PR:
		setMsk(PR.PRGEN,PR_AES_bm);
		break;
		case RTC_PR:
		setMsk(PR.PRGEN,PR_RTC_bm);
		break;
		case EVSYS_PR:
		setMsk(PR.PRGEN,PR_EVSYS_bm);
		break;
		case DMA_PR:
		setMsk(PR.PRGEN,PR_DMA_bm);
		break;
		/*DAC*/
		case DAC_PR:
		setMsk(PR.PRPB,PR_DAC_bm);
		break;
		/*ADC*/
		case ADC_PR:
		setMsk(PR.PRPA,PR_ADC_bm);
		break;
		/*AC*/
		case AC_PR:
		setMsk(PR.PRPA,PR_AC_bm);
		break;
		/*TWI*/
		case TWIC_PR:
		setMsk(PR.PRPC,PR_TWI_bm);
		break;
		case TWIE_PR:
		setMsk(PR.PRPE,PR_TWI_bm);
		break;
		/*USART*/
		case USARTC0_PR:
		setMsk(PR.PRPC,PR_USART0_bm);
		break;
		case USARTC1_PR:
		setMsk(PR.PRPC,PR_USART1_bm);
		break;
		case USARTD0_PR:
		setMsk(PR.PRPD,PR_USART0_bm);
		break;
		case USARTD1_PR:
		setMsk(PR.PRPD,PR_USART1_bm);
		break;
		case USARTE0_PR:
		setMsk(PR.PRPE,PR_USART0_bm);
		break;
		/*SPI*/
		case SPIC_PR:
		setMsk(PR.PRPC,PR_SPI_bm);
		break;
		case SPID_PR:
		setMsk(PR.PRPD,PR_SPI_bm);
		break;
		case SPIE_PR:
		setMsk(PR.PRPE,PR_SPI_bm);
		break;
		/*HIRES*/
		case HIRESC_PR:
		setMsk(PR.PRPC,PR_HIRES_bm);
		break;
		case HIRESD_PR:
		setMsk(PR.PRPD,PR_HIRES_bm);
		break;
		case HIRESE_PR:
		setMsk(PR.PRPE,PR_HIRES_bm);
		break;
		/*TC1*/
		case TC1C_PR:
		setMsk(PR.PRPC,PR_TC1_bm);
		break;
		case TC1D_PR:
		setMsk(PR.PRPD,PR_TC1_bm);
		break;
		/*TC0*/
		case TC0C_PR:
		setMsk(PR.PRPC,PR_TC0_bm);
		break;
		case TC0D_PR:
		setMsk(PR.PRPD,PR_TC0_bm);
		break;
		case TC0E_PR:
		setMsk(PR.PRPE,PR_TC0_bm);
		break;
		case ALL_PR:
		setMsk(PR.PRGEN,0xFF);
		setMsk(PR.PRPA,0xFF);
		setMsk(PR.PRPB,0xFF);
		setMsk(PR.PRPC,0xFF);
		setMsk(PR.PRPD,0xFF);
		setMsk(PR.PRPE,0xFF);
		break;
	}
}
void prEnable(peripheral_t pr)
{
	switch (pr)
	{
		case USB_PR:
		clrMsk(PR.PRGEN,PR_USB_bm);
		break;
		case AES_PR:
		clrMsk(PR.PRGEN,PR_AES_bm);
		break;
		case RTC_PR:
		clrMsk(PR.PRGEN,PR_RTC_bm);
		break;
		case EVSYS_PR:
		clrMsk(PR.PRGEN,PR_EVSYS_bm);
		break;
		case DMA_PR:
		clrMsk(PR.PRGEN,PR_DMA_bm);
		break;
		/*DAC*/
		case DAC_PR:
		clrMsk(PR.PRPB,PR_DAC_bm);
		break;
		/*ADC*/
		case ADC_PR:
		clrMsk(PR.PRPA,PR_ADC_bm);
		break;
		/*AC*/
		case AC_PR:
		clrMsk(PR.PRPA,PR_AC_bm);
		break;
		/*TWI*/
		case TWIC_PR:
		clrMsk(PR.PRPC,PR_TWI_bm);
		break;
		case TWIE_PR:
		clrMsk(PR.PRPE,PR_TWI_bm);
		break;
		/*USART*/
		case USARTC0_PR:
		clrMsk(PR.PRPC,PR_USART0_bm);
		break;
		case USARTC1_PR:
		clrMsk(PR.PRPC,PR_USART1_bm);
		break;
		case USARTD0_PR:
		clrMsk(PR.PRPD,PR_USART0_bm);
		break;
		case USARTD1_PR:
		clrMsk(PR.PRPD,PR_USART1_bm);
		break;
		case USARTE0_PR:
		clrMsk(PR.PRPE,PR_USART0_bm);
		break;
		/*SPI*/
		case SPIC_PR:
		clrMsk(PR.PRPC,PR_SPI_bm);
		break;
		case SPID_PR:
		clrMsk(PR.PRPD,PR_SPI_bm);
		break;
		case SPIE_PR:
		clrMsk(PR.PRPE,PR_SPI_bm);
		break;
		/*HIRES*/
		case HIRESC_PR:
		clrMsk(PR.PRPC,PR_HIRES_bm);
		break;
		case HIRESD_PR:
		clrMsk(PR.PRPD,PR_HIRES_bm);
		break;
		case HIRESE_PR:
		clrMsk(PR.PRPE,PR_HIRES_bm);
		break;
		/*TC1*/
		case TC1C_PR:
		clrMsk(PR.PRPC,PR_TC1_bm);
		break;
		case TC1D_PR:
		clrMsk(PR.PRPD,PR_TC1_bm);
		break;
		/*TC0*/
		case TC0C_PR:
		clrMsk(PR.PRPC,PR_TC0_bm);
		break;
		case TC0D_PR:
		clrMsk(PR.PRPD,PR_TC0_bm);
		break;
		case TC0E_PR:
		clrMsk(PR.PRPE,PR_TC0_bm);
		break;
		case ALL_PR:
		clrMsk(PR.PRGEN,0xFF);
		clrMsk(PR.PRPA,0xFF);
		clrMsk(PR.PRPB,0xFF);
		clrMsk(PR.PRPC,0xFF);
		clrMsk(PR.PRPD,0xFF);
		clrMsk(PR.PRPE,0xFF);
		break;
	}
}
void brdInit()
{
	//power down everything by default
	prDisable(ALL_PR);
	//set the CPU/peripheral clock to 32MHz
	clkInit_32MHz();	
	//setup the ADC
	prEnable(TC0E_PR);
	adcSetup();
	//setup the DAC
	dacSetup();

	
#if defined (__AVR_ATxmega32A4U__)	
	// sets the default state of Write Protect, Hold, and Chip Select to high
	PORTC.OUTSET =	0x1D;
	// enable status LED, and Ext Flash Pins for output	
	PORTC.DIRSET =	0xBD;
	
	//set direction of usartd1 tx line
	PORTD.DIRSET = 0x80;
#else
	//sets led high (off)
	PORTR.OUTSET =	0x02;
	// enable status LED
	PORTR.DIRSET =	0x02;
	
	//set direction of usartd1 tx line
	PORTC.DIRSET = 0x08;

#endif	

	//setup external memory interface
	spiInit();
	
	//setup the communication interface to the PC
	comPortInit();		
	prEnable(EVSYS_PR);
	prEnable(TC0C_PR);
	prEnable(TC1C_PR);
	prEnable(TC0D_PR);
	prEnable(TC1D_PR);

}

uint8_t ReadCalibrationByte( uint8_t index ){
	uint8_t result;

	/* Load the NVM Command register to read the calibration row. */
	NVM_CMD = NVM_CMD_READ_CALIB_ROW_gc;
	result = pgm_read_byte(index);

	/* Clean up NVM Command register. */
	NVM_CMD = NVM_CMD_NO_OPERATION_gc;

	return( result );
}

void resetDaq()
{
	CCP = CCP_IOREG_gc;
	RST.CTRL = RST_SWRST_bm;
}